package com.cjm.one.custom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.cjm.one.common.constant.SecurityConstants;
import com.cjm.one.common.exception.GlobalException;
import com.cjm.one.common.result.Result;
import com.cjm.one.common.result.ResultCodeEnum;
import com.cjm.one.common.utils.OrderIdGenerator;
import com.cjm.one.coupon.client.CustomerCouponClient;
import com.cjm.one.custom.mapper.CustomGradeMapper;
import com.cjm.one.custom.mapper.CustomerBalanceRecordMapper;
import com.cjm.one.custom.mapper.CustomerInfoMapper;
import com.cjm.one.custom.service.CustomerBalanceRecordService;
import com.cjm.one.custom.service.CustomerInfoService;
import com.cjm.one.model.base.TokenVo;
import com.cjm.one.model.coupon.dto.CouponConfirmDto;
import com.cjm.one.model.custom.entity.CustomGrade;
import com.cjm.one.model.custom.entity.CustomerBalanceRecord;
import com.cjm.one.model.custom.entity.CustomerInfo;
import com.cjm.one.model.custom.vo.RegisterVO;
import com.cjm.one.model.order.entity.OrderInfo;
import com.cjm.one.model.order.entity.OrderItem;
import com.cjm.one.model.order.enums.OrderStatusEnum;
import com.cjm.one.model.order.vo.OrderInfoVo;
import com.cjm.one.model.payment.BalanceDto;
import com.cjm.one.model.payment.enums.PayStatus;
import com.cjm.one.model.payment.enums.RechargeType;
import com.cjm.one.model.payment.enums.RecordType;
import com.cjm.one.model.system.vo.LoginVo;
import com.cjm.one.order.client.OrderInfoClient;
import com.cjm.one.security.custom.CustomPasswordEncoder;
import com.cjm.one.security.custom.SaltGenerator;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* @author 29289
* @description 针对表【customer_info(客户表)】的数据库操作Service实现
* @createDate 2024-11-04 16:20:11
*/
@Service
@Slf4j
public class CustomerInfoServiceImpl extends ServiceImpl<CustomerInfoMapper, CustomerInfo>
    implements CustomerInfoService {
    @Resource
    private OrderInfoClient orderInfoClient;
    @Resource
    private CustomerInfoMapper customerInfoMapper;

    @Resource
    private CustomerBalanceRecordMapper customerBalanceRecordMapper;
    @Resource
    private CustomPasswordEncoder customPasswordEncoder;

    @Resource
    private CustomGradeMapper customGradeMapper;
    @Resource
    private CustomerCouponClient customerCouponClient;
    @Override
    public Page<CustomerInfo> getUserList(Integer current, Integer size, String name, String phone, Long userId, String level,String email) {
        Page<CustomerInfo> page = new Page<>(current, size);
        LambdaQueryWrapper<CustomerInfo> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasText(name)) {
            queryWrapper.like(CustomerInfo::getNickname, name);
        }
        if (StringUtils.hasText(email)) {
            queryWrapper.like(CustomerInfo::getEmail, email);
        }
        if (StringUtils.hasText(phone)) {
            queryWrapper.like(CustomerInfo::getPhone, phone);
        }
        if (userId != null) {
            queryWrapper.eq(CustomerInfo::getId, userId);
        }
        if (StringUtils.hasText(level)) {
            queryWrapper.eq(CustomerInfo::getUserGrade, level);
        }
        queryWrapper.select(CustomerInfo::getId,
                CustomerInfo::getNickname,
                CustomerInfo::getPhone,
                CustomerInfo::getUserGrade,
                CustomerInfo::getEmail,
                CustomerInfo::getUserLesson,
                CustomerInfo::getStatus,
                CustomerInfo::getAvatarUrl,
                CustomerInfo::getUserType,
                CustomerInfo::getGender,
                CustomerInfo::getBirthday,
                CustomerInfo::getBalance,
                CustomerInfo::getCreateTime,
                CustomerInfo::getUpdateTime
        );
        return customerInfoMapper.selectPage(page, queryWrapper);
    }

    @Override
    public Boolean updateByIdInfo(CustomerInfo customerInfo) {
        CustomerInfo customerInfo1 = customerInfoMapper.selectById(customerInfo.getId());
        // 判断等级是否改变
        if (customerInfo.getUserGrade() != customerInfo1.getUserGrade()) {
            LambdaQueryWrapper<CustomGrade> customGradeLambdaQueryWrapper = new LambdaQueryWrapper<>();
            customGradeLambdaQueryWrapper.eq(CustomGrade::getGradeNam, customerInfo.getUserGrade());
            CustomGrade customGrade = customGradeMapper.selectOne(customGradeLambdaQueryWrapper);
            if (customGrade == null) {
                return false;
            }
            customerInfo.setUserLesson(customGrade.getLesson());

        }
        return customerInfoMapper.updateById(customerInfo) > 0;

    }

    @Override
    public CustomerInfo getByEmail(String email) {
        LambdaQueryWrapper<CustomerInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerInfo::getEmail, email);
        return customerInfoMapper.selectOne(queryWrapper);
    }

    @Override
    public CustomerInfo getByPhone(String phone) {
        LambdaQueryWrapper<CustomerInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerInfo::getPhone, phone);
        return customerInfoMapper.selectOne(queryWrapper);
    }

    @Override
    public TokenVo login(LoginVo loginVo) {
        TokenVo tokenVo = new TokenVo();
        tokenVo.setToken("111111111");
        return tokenVo;
    }



    @Override
    public Boolean register(RegisterVO registerVO) {
        LambdaQueryWrapper<CustomerInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CustomerInfo::getEmail, registerVO.getEmail());
        Long l = customerInfoMapper.selectCount(queryWrapper);
        if (l > 0) {
            throw new GlobalException(ResultCodeEnum.EMAL_USER_EXIST);
        }
        CustomerInfo customerInfo = new CustomerInfo();
        String salt = SaltGenerator.generateSalt();
        String encodePassword = customPasswordEncoder.encode(registerVO.getPassword()+salt);
        customerInfo.setPassword(encodePassword);
        customerInfo.setSalt(salt);
        customerInfo.setEmail(registerVO.getEmail());
        customerInfo.setNickname("用户");
        customerInfo.setAvatarUrl("https://cdn.pixabay.com/photo/2015/10/05/22/37/blank-profile-picture-973460_1280.png");
        customerInfo.setStatus(1);
        customerInfo.setUserGrade(0);
        customerInfo.setUserLesson(0L);
        int insert = customerInfoMapper.insert(customerInfo);
        return insert > 0 ;
    }

    @Override
    public Boolean addBalance(Long id, BigDecimal value) {
        //TODO: 仅暂时添加余额
        CustomerInfo customerInfo = customerInfoMapper.selectById(id);
        BigDecimal oldBalance = customerInfo.getBalance();
        BigDecimal newBalance = oldBalance.add(value);
        LambdaUpdateWrapper<CustomerInfo> customerInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        customerInfoLambdaUpdateWrapper.eq(CustomerInfo::getId, id);
        customerInfoLambdaUpdateWrapper.set(CustomerInfo::getBalance, newBalance);
        int update = customerInfoMapper.update(customerInfoLambdaUpdateWrapper);

            //创建充值订单编号
            OrderIdGenerator generator = new OrderIdGenerator(123);
            String OrderNo = "R" + generator.generate();
            CustomerBalanceRecord customerBalanceRecord = new CustomerBalanceRecord();
            customerBalanceRecord.setAfterBalance( newBalance);
            customerBalanceRecord.setBeforeBalance(oldBalance);
            customerBalanceRecord.setCustomerId(id);
            customerBalanceRecord.setOrderId(OrderNo);
            customerBalanceRecord.setRemark("余额充值");
            customerBalanceRecord.setAmount(value);
            customerBalanceRecord.setRecordType(RecordType.RECHARGE);
            customerBalanceRecord.setStatus(update>0? PayStatus.SUCCESS : PayStatus.FAIL);
            customerBalanceRecord.setChannel(RechargeType.ALIPAY);
             customerBalanceRecordMapper.insert(customerBalanceRecord);

        return update>0;
    }

    @Override
    public Long pay(BalanceDto balanceDto) {
        //TODO: 缺少事务
        OrderInfoVo orderInfo = orderInfoClient.getByorderNo(balanceDto.getOrderNo(), SecurityConstants.INNER).getData();
        if (orderInfo == null) {
            throw new GlobalException(ResultCodeEnum.ORDER_NOT_EXIST);
        }
        batchUseCoupon(orderInfo);

        CustomerInfo customerInfo = customerInfoMapper.selectById(orderInfo.getCustomId());
        String password = balanceDto.getPassword();
        String payPassword = customerInfo.getPayPassword();
        boolean matches = customPasswordEncoder.matches(password+ customerInfo.getPaySalt(), payPassword);
        if (!matches) {
            throw new GlobalException(ResultCodeEnum.PAY_PASSWORD_ERROR);
        }
        BigDecimal balance = customerInfo.getBalance();
        BigDecimal totalAmount = orderInfo.getTotalAmount();
        if (balance.compareTo(totalAmount) < 0) {
            throw new GlobalException(ResultCodeEnum.BALANCE_NOT_ENOUGH);
        }
        BigDecimal newBalance = balance.subtract(totalAmount);
        LambdaUpdateWrapper<CustomerInfo> customerInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        customerInfoLambdaUpdateWrapper.eq(CustomerInfo::getId, orderInfo.getCustomId());
        customerInfoLambdaUpdateWrapper.set(CustomerInfo::getBalance, newBalance);
        customerInfoMapper.update(customerInfoLambdaUpdateWrapper);
        //添加余额记录
        CustomerBalanceRecord customerBalanceRecord = new CustomerBalanceRecord();
        customerBalanceRecord.setAfterBalance(newBalance);
        customerBalanceRecord.setBeforeBalance(balance);
        customerBalanceRecord.setAmount(totalAmount);
        customerBalanceRecord.setStatus(PayStatus.SUCCESS);
        customerBalanceRecord.setOrderId("P"+orderInfo.getOrderNo());
        customerBalanceRecord.setRemark("订单支付");
        customerBalanceRecord.setRecordType(RecordType.EXPENSES);
        customerBalanceRecord.setCustomerId(orderInfo.getCustomId());
        customerBalanceRecordMapper.insert(customerBalanceRecord);

        orderInfo.setOrderStatus(OrderStatusEnum.WAIT_DELIVER);


        orderInfo.setPaymentTime(LocalDateTime.now());
        orderInfoClient.updateOrder(orderInfo,SecurityConstants.INNER);
        return orderInfo.getId();
    }
    public void batchUseCoupon(OrderInfoVo orderInfo) {
        CouponConfirmDto couponConfirmDto = new CouponConfirmDto();
        couponConfirmDto.setUserId(orderInfo.getCustomId());
        couponConfirmDto.setOrderId(orderInfo.getId());
        log.info("couponIds:{}",orderInfo.getOrderItemList());
        List<OrderItem> orderItems = Optional.ofNullable(orderInfo.getOrderItemList())
                .orElse(Collections.emptyList());
        ArrayList<Long> longs = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            if (orderItem.getCouponId() != null) {
                longs.add(orderItem.getCouponId());
            }
        }
        couponConfirmDto.setCouponIds(longs);

        customerCouponClient.batchConfirmUse(couponConfirmDto,SecurityConstants.INNER);
    }

    @Override
    public Boolean refund(String orderNo) {
        OrderInfoVo data = orderInfoClient.getByorderNo(orderNo, SecurityConstants.INNER).getData();
        if (data == null) {
            throw new GlobalException(ResultCodeEnum.ORDER_NOT_EXIST);
        }
        CustomerInfo customerInfo = customerInfoMapper.selectById(data.getCustomId());
        BigDecimal balance = customerInfo.getBalance();
        BigDecimal totalAmount = data.getTotalAmount();
        BigDecimal newBalance = balance.add(totalAmount);
        LambdaUpdateWrapper<CustomerInfo> customerInfoLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        customerInfoLambdaUpdateWrapper.eq(CustomerInfo::getId, data.getCustomId());
        customerInfoLambdaUpdateWrapper.set(CustomerInfo::getBalance, newBalance);
        customerInfoMapper.update(customerInfoLambdaUpdateWrapper);
        //添加余额记录
        CustomerBalanceRecord customerBalanceRecord = new CustomerBalanceRecord();
        customerBalanceRecord.setAfterBalance(newBalance);
        customerBalanceRecord.setBeforeBalance(balance);
        customerBalanceRecord.setAmount(totalAmount);
        customerBalanceRecord.setStatus(PayStatus.SUCCESS);
        customerBalanceRecord.setOrderId("PR"+data.getOrderNo());
        customerBalanceRecord.setRemark("订单退款");
        customerBalanceRecord.setRecordType(RecordType.RECHARGE);
        customerBalanceRecord.setCustomerId(data.getCustomId());
        customerBalanceRecordMapper.insert(customerBalanceRecord);
        data.setOrderStatus(OrderStatusEnum.REFUNDED);
        data.setRefundTime(LocalDateTime.now());
        orderInfoClient.updateOrder(data,SecurityConstants.INNER);
        return true;
    }



}




